<?php
/**
 *	Actions for Bugs.
 *	@package		tools.BugTracker
 *	@author			Christian Würker <Christian.Wuerker@CeuS-Media.de>
 *	@since			01.11.2005
 *	@version		1.0
 */
/**
 *	Actions for Bugs.
 *	@package		tools.BugTracker
 *	@extends		CMF_Krypton_Core_DefinitionAction
 *	@uses			User
 *	@uses			Bug
 *	@uses			Comment
 *	@uses			Attachment
 *	@uses			Assignment
 *	@uses			Search
 *	@uses			MessageActions
 *	@uses			BugViews
 *	@author			Christian Würker <Christian.Wuerker@CeuS-Media.de>
 *	@since			01.11.2005
 *	@version		1.0
 */
class Action_Bug_Manager extends CMF_Krypton_Core_DefinitionAction
{
	public function __construct()
	{
		parent::__construct();
		$this->loadLanguage( 'bug' );
	}

	public function act()
	{
		$request	= $this->registry->get( 'request' );
		$session	= $this->registry->get( 'session' );
		$auth		= $this->registry->get( 'auth' );


#		if( !$auth->hasRight( $request->get( 'link' ), 'navigate' ) )
#			$this->restart( "./" );	

		if( $request->has( 'resetFilters' ) )
			$this->resetFilters();

		if( $bug_id = $request->get( 'bug_id' ) )
		{
			if( $request->get( 'editBug' ) )
				$this->editBug();
			else if( $request->get( 'addComment' ) )
				$this->addComment();
			else if( $request->get( 'addAttachment' ) )
				$this->addAttachment();
			else if( $request->get( 'addDeveloper' ) )
				$this->addDeveloper();
			else if( $request->get( 'removeDeveloper' ) )
				$this->removeDeveloper();
			else if( $request->get( 'sendMessage' ) )
			{
				$action	= new MessageActions();
				$action->sendMessage();
			}
		}
		else if( $search_id	= $request->get( 'search_id' ) )
		{
			if( $request->get( 'removeSearch' ) )
			{
				$search		= new Search( $search_id );
				$search->deleteData();
			}
			else
			{
				$search		= new Search( $search_id );
				$data		= $search->getData( false, true );
				print_m( $data );
				$parameters	= explode( "&&", $data['parameters'] );
				foreach( $parameters as $parameter )
				{
					list( $key, $value )	= explode( "==", $parameter );
					if( $key	== "status" )
						$value	= explode( "|", $value );
					$session->set( "bug_".$key, $value );
				}
				foreach( $search->fields as $field )
				{
					$value	= isset( $param[$field] ) ? $param[$field] : "";
					$session->set( 'search_'.$field, $value );
				}
				$session->set( 'search_offset',		0 );
			}
		}
		$this->filterBugs();
	}
	/**
	 *	Adds a Bug Report and sends eMails to all Managers.
	 *	@access		private
	 *	@return		void
	 */
	private function addBug()
	{
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$mail		= $this->registry->get( 'mail' );

		if( $title = $request->get( 'add_title' ) )
		{
			if( $description = $request->get( 'add_description' ) )
			{
				$timestamp	= time();
				$author		= $auth->getCurrentUser();
				$parts		= explode( ":", $request->get( 'add_project' ) );
				$server		= $parts[0];
				$project	= $parts[1];
				$data		= array(
					"title"			=> $title,
					"description"	=> $description,
					"author"		=> $author,
					"status"		=> 0,
					"type"			=> $request->get( 'add_type' ),
					"priority"		=> $request->get( 'add_priority' ),
					"server"		=> $server,
					"project"		=> $project,
					"location"		=> $request->get( 'add_location' ),
					"function"		=> $request->get( 'add_function' ),
					"created"		=> time(),
					"modified"		=> time(),
					);
				$bug	= new Bug();
				$bug_id	= $bug->addData( $data );
				$bug->focusPrimary( $bug_id );
				$bugdata	= $bug->getData( false, true );
				$request->remove( 'add_title' );
				$request->remove( 'add_description' );
				$request->remove( 'add_type' );
				$request->remove( 'add_priority' );
				$this->messenger->noteSuccess( $this->words['bug']['msg']['success1'] );

				//  --  SEND MAIL  --  //
				$from	= $auth->getCurrentUser();
				$user	= new User();
				$users	= $user->getAllData();
				$users	= $users[$user->getTableName()];
				$view	= new BugViews();
				$info	= $view->buildInformationBlock( $bugdata );
				$subject	= "Bug #".$bugdata['bug_id']." added.";
				$body	= "Bug #".$bugdata['bug_id']." has been added.\n\n".$info;
				foreach( $users as $entry )
				{
					if( $entry['notify'] )
					{
						if( $user->hasRole( $entry['user_id'], 2 ) )		//  is a Manager
						{
							if( $entry['user_id'] != $from )
							{
								if( $mail->sendMail( $from, $entry['user_id'], $subject, $body ) )
									$this->messenger->noteSuccess( $this->words['bug']['msg']['success9'], $entry['username'] );
								else
									$this->messenger->noteError( $this->words['bug']['msg']['error9'], $entry['username'] );
							}
						}
					}
				}
			}
			else
				$this->messenger->noteError( $this->words['bug']['msg']['error3'] );
		}
		else
			$this->messenger->noteError( $this->words['bug']['msg']['error2'] );
	}

	/**
	 *	Edits a Bug Report and sends eMails to all Listeners.
	 *	@access		private
	 *	@return		void
	 */
	private function editBug()
	{
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$mail		= $this->registry->get( 'mail' );

		if( $bug_id = $request->get( 'bug_id' ) )
		{
			$bug	= new Bug( $bug_id );
			$bugdata	= $bug->getData( false, true );
			$parts	= explode( ":", $request->get( 'edit_project' ) );
			$server	= $parts[0];
			$project	= $parts[1];
			$data	= array(
				"title"			=> $request->get( 'edit_title' ),
				"description"	=> $request->get( 'edit_description' ),
				"type"			=> $request->get( 'edit_type' ),
				"status"		=> $request->get( 'edit_status' ),
				"priority"		=> $request->get( 'edit_priority' ),
				"server"		=> $server,
				"project"		=> $project,
				"location"		=> $request->get( 'edit_location' ),
				"function"		=> $request->get( 'edit_function' ),
				"edited"		=> time(),
				);
			$bug->modifyData( $data );
			$this->messenger->noteSuccess( $this->words['bug']['msg']['success2'] );
			if( $comment = $request->get( 'edit_comment' ) )
			{
				$data	= array(
					"bug_id"		=> $bug_id,
					"comment"		=> $comment,
					"author"		=> $auth->getCurrentUser(),
					"status"		=> $request->get( 'edit_status' ),
					"timestamp"		=> time(),
					);
				$comment = new Comment();
				$comment->addData( $data, false );
				$this->messenger->noteSuccess( $this->words['bug']['msg']['success3'] );
			}
			//  --  SEND MAIL  --  //
			$bug	= new Bug( $bug_id);
			$data	= $bug->getData( false, true );
			$view	= new BugViews();
			
			$info	= $view->buildInformationBlock( $data, $bugdata );
			$subject	= "Bug #".$bugdata['bug_id']." edited.";
			$body	= "Bug #".$bugdata['bug_id']." has been edited.\n\n".$info;
			$this->sendMail( $bug_id, $subject, $body );
		}
		else
			$this->messenger->noteError( $this->words['bug']['msg']['error1'] );
	}

	/**
	 *	Adds a Comment and sends eMails to all Listeners.
	 *	@access		private
	 *	@return		void
	 */
	private function addComment()
	{
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$mail		= $this->registry->get( 'mail' );

		if( $bug_id = $request->get( 'bug_id' ) )
		{
			$bug	= new Bug( $bug_id );
			$bugdata	= $bug->getData( false, true );
			if( $comment = $request->get( 'add_comment' ) )
			{
				$data	= array(
					"bug_id"		=> $bug_id,
					"comment"	=> $comment,
					"author"		=> $auth->getCurrentUser(),
					"status"		=> $bugdata['status'],
					"timestamp"	=> time(),
					);
				$comment = new Comment();
				$comment->addData( $data );
				$this->messenger->noteSuccess( $this->words['bug']['msg']['success3'] );
				//  --  SEND MAIL  --  //
				$view	= new BugViews();
				$info	= $view->buildInformationBlock( $bugdata );
				$subject	= "Bug #".$bugdata['bug_id']." commented.";
				$body	= "Bug #".$bugdata['bug_id']." has been commented.\n\n".$info;
				$this->sendMail( $bug_id, $subject, $body );
			}
			else
				$this->messenger->noteError( $this->words['bug']['msg']['error4'] );
		}
		else
			$this->messenger->noteError( $this->words['bug']['msg']['error1'] );
	}

	/**
	 *	Adds an Attachment.
	 *	@access		private
	 *	@return		void
	 */
	private function addAttachment()
	{
		$config		= $this->registry->get( 'config' );
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$words		= $this->words['bug']['msg'];
		
		$bug_id	= $request->get( 'bug_id' );

		if( $this->validateForm( 'bug', 'addAttachment', 'bug', 'attachment' ) )
		{
			$title = $request->get( 'title' );
			$source	= $_FILES['attachment']['tmp_name'];
			$target	= $config['paths']['attachments'].$_FILES['attachment']['name'];
			$i=0;
			while( file_exists( $target ) )
			{
				$i++;
				$info	= pathinfo( $target );
				$info['basename'] = substr( $info['basename'], 0, -(1+ strlen( $info['extension'] ) ) );
				if( $i>1 )
					$info['basename'] = substr( $info['basename'], 0, -(1+strlen( $i ) ) );
				$target	= $info['dirname']."/".$info['basename']."-".$i.".".$info['extension'];
			}

			$info	= pathinfo( $_FILES['attachment']['name'] );
			if( !in_array( $info['extension'], explode( ",", $config['config']['allowed_upload_extension'] ) ) )
			{
				$exts	= implode( ", ", explode( ",", $config['config']['allowed_upload_extension'] ) );
				$this->messenger->noteError( $words['error10'], $info['extension'], $exts );
				return false;
			}
			move_uploaded_file( $source, $target );
			$description	= $request->get( 'description' );
			$data	= array(
				"bug_id"		=> $bug_id,
				"title"		=> $title,
				"description"	=> $description,
				"filename"	=> basename( $target ),
				);
			$attachment	= new Attachment();
			$attachment->addData( $data );

			$comment	= new Comment();
			$text		= $this->words['bug']['attachment']['comment'];
			$text		= str_replace( "#file#", basename( $target ), $text );
			$text		= str_replace( "#title#", $title, $text );
			$text		= str_replace( "#desc#", $description, $text );
			$data	= array(
				"bug_id"		=> $bug_id,
				"comment"	=> $text,
				"author"		=> $auth->getCurrentUser(),
				"timestamp"	=> time(),
				);
			$comment = new Comment();
			$comment->addData( $data );
			$this->messenger->noteSuccess( $words['success4'] );
		}
	}

	/**
	 *	Stores all Search Conditions into Session.
	 *	@access		private
	 *	@return		void
	 */
	private function filterBugs()
	{
		$config		= $this->registry->get( 'config' );
		$request	= $this->registry->get( 'request' );
		$session	= $this->registry->get( 'session' );
		$auth		= $this->registry->get( 'auth' );
		$words		= $this->words['bug']['msg'];

		if( $request->has( 'filterBugs' ) )
		{
			$session->set( 'bug_bug_id',	$request->get( 'filter_bug_id' ) );
			$session->set( 'bug_server',	$request->get( 'filter_server' ) );
			$session->set( 'bug_project',	$request->get( 'filter_project' ) );
			$session->set( 'bug_type',		$request->get( 'filter_type' ) );
			$session->set( 'bug_priority',	$request->get( 'filter_priority' ) );
			$session->set( 'bug_title',		$request->get( 'filter_title' ) );
			$session->set( 'bug_reporter',	$request->get( 'filter_reporter' ) );
			$session->set( 'bug_developer',	$request->get( 'filter_developer' ) );
			$session->set( 'bug_status',	is_array( $request->get( 'filter_status' ) ) ? $request->get( 'filter_status' ) : array( $request->get( 'filter_status' ) ) );
			$session->set( 'bug_order',		$request->get( 'filter_order' ) );
			$session->set( 'bug_limit',		$request->get( 'filter_limit' ) );
			$session->set( 'bug_direction',	$request->get( 'filter_direction' ) );
			$session->set( 'bug_offset',	0 );

			if( $title	= $request->get( 'filter_save' ) )
			{
				$search	= new Search();
				$data	= array();
				foreach( $search->fields as $field )
					if( $value = $request->get( 'filter_'.$field ) )
					{
						if( $field == "status" )
							$value	= implode( "|", $value );
						$data[]	= $field."==".$value;
					}
				$data	= implode( "&&", $data );
				$data	= array(
					"user_id"		=> $auth->getCurrentUser(),
					"title"		=> $title,
					"parameters"	=> $data,
					"timestamp"	=> time()
				);
				$search->addData( $data );
				$this->messenger->noteSuccess( $words['success10'], $title );
			}
			if( (int)$session->get( 'bug_limit' ) < 1 )
				$session->set( 'bug_limit', $config['layout']['list_limit'] );
		}
		else
		{
			if( NULL !== $request->get( 'filter_offset' ) )
				$session->set( 'bug_offset', $request->get( 'filter_offset' ) );
			if( !$request->get( 'filter_limit' ) )
				$session->set( 'bug_limit', $config['layout']['list_limit'] );
		}
			
	}

	/**
	 *	Assigns Developers to a Bug and sends eMails to Developers.
	 *	@access		private
	 *	@return		void
	 */
	private function addDeveloper()
	{
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$mail		= $this->registry->get( 'mail' );

		if( $bug_id	= $request->get( "bug_id" ) )
		{
//			if( $this->validateForm( 'bug', 
			$developers	= (array) $request->get( "developers" );
			foreach( $developers as $developer_id )
			{
				$data	= array(
					"bug_id"	=> $bug_id,
					"user_id"	=> $developer_id,
				);
				$assign	= new Assignment();
				$assign->addData( $data );

				$bug	= new Bug( $bug_id );
				$bugdata	= $bug->getData( false, true );
				if( $bugdata['status'] < 1 )
				{
					$bug->modifyData( array( "status" => 1 ) );
					$bug->modifyData( array( "timestamp" => time() ) );
				}

				//  --  MESSAGE  --  //
				$user	= new User( $developer_id );
				$data	= $user->getData( false, true );
				$this->messenger->noteSuccess( $this->words['bug']['msg']['success5'], $data['username'] );

				//  --  SEND MAIL  --  //
				$dev	= new User( $developer_id );
				$dev	= $user->getData( false, true );
				if( $dev['notify'] )
				{
					$from	= $auth->getCurrentUser();
					$to		= $developer_id;
					$view	= new BugViews();
					$info	= $view->buildInformationBlock( $bugdata );
					$subject	= "Bug #".$bugdata['bug_id']." assigned.";
					$body	= "Bug #".$bugdata['bug_id']." has been asigned to you.\n\n".$info;
					if( $mail->sendMail( $from, $to, $subject, $body ) )
						$this->messenger->noteSuccess( $this->words['bug']['msg']['success8'], $dev['username'] );
					else
						$this->messenger->noteError( $this->words['bug']['msg']['error8'], $dev['username'] );
				}
			}
		}
		else
			$this->messenger->noteError( $this->words['bug']['msg']['error1'] );
	}

	/**
	 *	Unassigns Developers from a Bug and sends eMails to Developers.
	 *	@access		private
	 *	@return		void
	 */
	private function removeDeveloper()
	{
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$mail		= $this->registry->get( 'mail' );

		if( $bug_id	= $request->get( "bug_id" ) )
		{
			$developers	= (array) $request->get( "developers_has" );
			foreach( $developers as $developer_id )
			{
				$assign	= new Assignment();
				$assign->focusForeign( "bug_id", $bug_id );
				$assign->focusForeign( "user_id", $developer_id );
				$assign->deleteData();

				$bug	= new Bug( $bug_id );
				$bugdata	= $bug->getData( false, true );
				$assign	= new Assignment();
				$assign->focusForeign( "bug_id", $bug_id );
				$devs	= $assign->getData( false );
				if( !count( $devs ) )
				{
					$bug->modifyData( array( "status" => 0 ) );
					$bug->modifyData( array( "timestamp" => time() ) );
				}

				//  --  MESSAGE  --  //
				$user	= new User( $developer_id );
				$user	= $user->getData( false, true );
				$this->messenger->noteSuccess( $this->words['bug']['msg']['success6'], $user['username'] );

				//  --  SEND MAIL  --  //
				$dev	= new User( $developer_id );
				$dev	= $dev->getData( false, true );
				if( $dev['notify'] )
				{
					$from		= $auth->getCurrentUser();
					$to			= $developer_id;
					$view		= new BugViews();
					$info		= $view->buildInformationBlock( $bugdata );
					$subject	= "Bug #".$bugdata['bug_id']." released.";
					$body		= "Bug #".$bugdata['bug_id']." has been released from you.\n\n".$info;
					if( $mail->sendMail( $from, $to, $subject, $body ) )
						$this->messenger->noteSuccess( $this->words['bug']['msg']['success8'], $dev['username'] );
					else
						$this->messenger->noteError( $this->words['bug']['msg']['error8'], $dev['username'] );
				}
			}
		}
		else
			$this->messenger->noteError( $this->words['bug']['msg']['error1'] );
	}

	/**
	 *	Sends eMails to all Listeners of a Bug Report.
	 *	@access		private
	 *	@return		void
	 */
	private function sendMail( $bug_id, $subject, $body )
	{
		$request	= $this->registry->get( 'request' );
		$auth		= $this->registry->get( 'auth' );
		$mail		= $this->registry->get( 'mail' );

		$listeners	= array();
		$current	= $auth->getCurrentUser();

		$bug	= new Bug( $bug_id );
		$bugdata	= $bug->getData( false, true );

		//  --  AUTHOR  --  //
		$listeners[]	= $bugdata['author'];

		//  --  DEVELOPERS  --  //
		$assign	= new Assignment();
		$assign->focusForeign( "bug_id", $bug_id );
		$devs	= $assign->getData( false );
		foreach( $devs as $dev )
			$listeners[] = $dev['user_id'];

		//  --  MANAGERS  --  //
		$assign	= new Assignment();
		$assign->focusForeign( "bug_id", $bug_id );
		$mans	= $assign->getData( false );
		foreach( $mans as $man )
			$listeners[] = $man['user_id'];
		$listeners	= array_unique( $listeners );

		//  --  DEVELOPERS  --  //
		foreach( $listeners as $listener )
		{
			if( $current != $listener )
			{
				$listener	= new User( $listener );
				$listener	= $listener->getData( false, true );
				if( (bool)$listener['notify'] )
				{
					if( $mail->sendMail( $current, $listener['user_id'], $subject, $body ) )
						$this->messenger->noteSuccess( $this->words['bug']['msg']['success7'], $listener['username'] );
					else
						$this->messenger->noteError( $this->words['bug']['msg']['error7'], $listener['username'] );
				}
			}
		}
	}
	
	function resetFilters()
	{
		$session	= $this->registry->get( 'session' );
		foreach( array_keys( $session->getAll() ) as $key )
			if( preg_match( "@^bug_@i", $key ) )
				$session->remove( $key );
	}
	
}
?>
